/*
 * @Description: mongo_db 数据连接
 * @Version: 1.0
 * @Autor: jiajun wu
 * @Date: 2021-08-15 01:30:49
 * @LastEditors: JiaJun Wu
 * @LastEditTime: 2021-09-23 17:04:17
 */
extern crate r2d2;
extern crate r2d2_mongodb;
use super::toml_conf::SETTING;
use r2d2::PooledConnection;
use r2d2_mongodb::{ConnectionOptionsBuilder, MongodbConnectionManager};
use rocket::http::Status;
use rocket::request::{FromRequest, Outcome};
use rocket::Request;
use std::ops::Deref;

type Pool = r2d2::Pool<MongodbConnectionManager>;

pub struct Connection(pub PooledConnection<MongodbConnectionManager>);

/// 初始化创建数据库连接池
pub fn init_pool() -> Pool {
    let manager = MongodbConnectionManager::new(
        ConnectionOptionsBuilder::new()
            .with_host(SETTING.data_base.mbp.host.as_str())
            .with_port(SETTING.data_base.mbp.port as u16)
            .with_db(SETTING.data_base.mbp.name.as_str())
            .with_username(SETTING.data_base.mbp.username.as_str())
            .with_password(SETTING.data_base.mbp.password.as_str())
            .build(),
    );

    match Pool::builder().max_size(2).build(manager) {
        Ok(pool) => pool,
        Err(e) => panic!("错误：无法创建mongodb池 {}", e),
    }
}

/// 创建FromRequest的实现，以便可以在每个api端点上提供Conn
#[rocket::async_trait]
impl<'r> FromRequest<'r> for Connection {
    type Error = ();

    async fn from_request(request: &'r Request<'_>) -> Outcome<Connection, ()> {
        let pool = request.rocket().state::<Pool>().unwrap();
        match pool.get() {
            Ok(db) => Outcome::Success(Connection(db)),
            Err(_) => Outcome::Failure((Status::ServiceUnavailable, ())),
        }
    }
}

/// 取消引用Conn时，返回mongo连接。
impl Deref for Connection {
    type Target = PooledConnection<MongodbConnectionManager>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
